import Bullet from "./Bullet";
import {Direction, ColliderGroups} from './constants/Enums';
import Game from "./Game";

const {ccclass, property} = cc._decorator;

/**
 * 飞行游戏不能有加速度,太影响手感.
 */
@ccclass
export default class Player extends cc.Component {
    /**
     * 主角水平方向速度.
     */
    @property({type:cc.Integer})
    xSpeed = 0;
    /**
     * 主角垂直方向速度.
     */
    @property({type:cc.Integer})
    ySpeed = 0;

    /**
     * 飞机开火间隔.
     */
    @property(cc.Integer)
    fireInterval = 0;

    @property(cc.SpriteFrame)
    playerSprite : cc.SpriteFrame = null;

    /**
     * 游戏主对象.
     */
    game:Game;

    /**
     * 移动方向
     */
    left = false;
    /**
     * 移动方向
     */
    right = false;
    /**
     * 移动方向
     */
    up = false;
    /**
     * 移动方向
     */
    down = false;

    /**
     * 开火中
     */
    onFire = false;

    /**
     * 上次开火时间
     */
    lastFireTime = 0;
    /**
     * 动画.
     */
    anim:cc.Animation;
    
    // LIFE-CYCLE CALLBACKS:
    onLoad () {
        this.anim = <cc.Animation>this.node.getComponent(cc.Animation);
        //注册死亡动画播放完时的回调.player_destroy.另外一个动画player_fly由于设置是无限循环,因此不会触发finished.
        this.anim.on(cc.Animation.EventType.FINISHED,this.onAniminationFinished,this);

        this.init();
        
        //监听键盘事件.
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown,this);
        cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP,this.onKeyUp,this);
    }

    onDestroy () {
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown,this);
        cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP,this.onKeyUp,this);        
    }

    start () {
        
    }

    update (dt) {
        //根据当前移动方向每帧更新主角位置.
        if(this.left){
            this.node.x -= this.xSpeed * dt;
        }
        if(this.right){
            this.node.x += this.xSpeed * dt;
        }
        if(this.up){
            this.node.y += this.ySpeed * dt;
        }
        if(this.down){
            this.node.y -= this.ySpeed * dt;
        }

        //主角位置限制在屏幕内.
        if(this.node.x > this.node.parent.width/2 - this.node.width/2){
            this.node.x = this.node.parent.width/2 - this.node.width/2
        }else if(this.node.x < - this.node.parent.width/2 + this.node.width/2){
            this.node.x = - this.node.parent.width/2 + this.node.width/2
        }
        if(this.node.y > this.node.parent.height/2 - this.node.height/2){
            this.node.y = this.node.parent.height/2 - this.node.height/2
        }else if(this.node.y < - this.node.parent.height/2 + this.node.height/2){
            this.node.y = - this.node.parent.height/2 + this.node.height/2
        }

        if(this.onFire){
            let currTime = new Date().getTime();
            if(currTime - this.lastFireTime > this.fireInterval){
                this.lastFireTime = currTime
                this.fire();
            }
        }
    }

    // LIFE-CYCLE CALLBACKS END
    init(){
        let x = 0;
        let y = - this.node.parent.height/2 + this.node.height;
        this.node.setPosition(x,y)

        //解决重用敌机对象后,依然显示爆炸效果的问题.
        this.node.getComponent(cc.Sprite).spriteFrame = this.playerSprite;
        //飞行时的尾部动画
        let animState = this.anim.play('player_fly');
    }
    

    onKeyDown(event){
        switch(event.keyCode){
            case cc.macro.KEY.up:
                this.up=true;
            break;
            case cc.macro.KEY.down:
                this.down=true;
            break;
            case cc.macro.KEY.left:
                this.left = true;
                break;
            case cc.macro.KEY.right:
                this.right = true;
                break;
            case cc.macro.KEY.f:
                this.onFire = true;
                break;
            default:
                break;
        }
    }

    onKeyUp(event){
        switch(event.keyCode){
            case cc.macro.KEY.up:
                this.up = false;
                break;
            case cc.macro.KEY.down:
                this.down = false;
                break;
            case cc.macro.KEY.left:
                this.left = false;
                break;
            case cc.macro.KEY.right:
                this.right = false;
                break;
            case cc.macro.KEY.f:
                this.onFire = false;
                break;
            default:
                break;
        }
    }

    /**
     * 当碰撞产生的时候调用
     * @param  {cc.Collider} other 产生碰撞的另一个碰撞组件
     * @param  {cc.Collider} self  产生碰撞的自身的碰撞组件
     */
    onCollisionEnter(other:cc.Collider, self:cc.Collider) {
        // console.log('this Player will recycle');
        

        //把分组切换成默认,防止继续触发碰撞检测.
        this.node.group = ColliderGroups.Default;
        //停止飞行时的尾部动画
        this.anim.stop('player_fly');
        //播放死亡动画
        this.anim.play('player_destroy');
    }
    /**
     * 死亡动画播放完成时.
     */
    onAniminationFinished(){
        //首先检查生命值,不够则游戏结束,否则重新生成一个飞机.
        this.recycle();
        this.game.gameOver();
    }

    fire(){
        //创建子弹
        // let scene = cc.director.getScene();
        let bulletNode = this.game.pool.getBullet();
        bulletNode.active = true;//显示该节点及其所有子节点,启用所有组件和上面的update.
        //添加到场景
        this.node.parent.addChild(bulletNode);
        //设置
        let pos = new cc.Vec2(this.node.x,this.node.y+this.node.height/2);
        let script = bulletNode.getComponent(Bullet);
        script.init(pos,Direction.UP);
        script.game = this.game;
        //碰撞分组
        bulletNode.group = ColliderGroups.PlayerBullet;
    }
    /**
     * 回收到对象池.
     */
    recycle(){
        this.game.pool.putPlayer(this.node);
    }
}
